
  #include <sys/types.h>   
  #include <sys/socket.h>
#include<iostream>
#include<unistd.h>
#include<cstring>
#include<netinet/in.h>
       #include <arpa/inet.h>
#include<string>
#include<pthread.h>


#define SIZE 1024

struct ThreadData
{
  struct sockaddr_in  server ;
 int sockfd;
 std::string serverip; 
};
void * recv_message (void * args)
{
    ThreadData * td = (ThreadData *)args;
     char buffer [SIZE];
  while(true) 
  {
       struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
     
        ssize_t s = recvfrom(td->sockfd, buffer, 1023, 0, (struct sockaddr*)&temp, &len);
            if(s > 0)
        {
            buffer[s] = 0; //当成字符串处理
              std::cout << buffer <<   std::endl;
        }
  }

  
}

void * send_message (void * args)//发消息的线程
{
    ThreadData * td = (ThreadData *)args;
socklen_t len  =sizeof(td->server) ;
 std::string message;

 std::string welcome = td->serverip ; 
 welcome +="comming ...." ;
        sendto(td->sockfd, message.c_str(),message.size(),0, (  struct sockaddr *)&(td->server ) ,len);

 while(true )
    {
     
        //客户端发送数据给server
         std::cout << "Please Enter@ ";
        getline(std::cin, message);
        std::cout<<message<<std::endl;
        sendto(td->sockfd, message.c_str(),message.size(),0, (  struct sockaddr *)&(td->server ) ,len);
    }

}
void Usage(std::string proc)
{
    std::cout << "\n\rUsage: " << proc << " serverip serverport\n"
              << std::endl;
}


// ./udpclient serverip serverport

//多线程 
int main(int argc ,char * argv[] )
{
 if (argc != 3)
    {
        Usage(argv[0]);
        exit(0);
    }

    //agrc 为 3 


 std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);

struct ThreadData td;

bzero(& (td.server), sizeof(td.server));
td.server.sin_addr.s_addr=inet_addr(serverip.c_str());
td.server.sin_family= AF_INET;//IPV4
td.server.sin_port =htons(serverport);//保证端口号是网络字节序列，因为该端口号是要给对方发送的
  socklen_t len = sizeof(td.server);
    //创建客户端套接字
 td.sockfd = socket(AF_INET, SOCK_DGRAM, 0);  //IPv4,SOCK_DGRAM基于UDP的网络通信
   if (td.sockfd < 0)
    {
        std::cout << "socker error" << std::endl;
        return 1;
    }

    td.serverip =serverip ;


 pthread_t recvr ,sendr; //收消息的线程，发消息的线程

pthread_create(&recvr,nullptr ,recv_message ,&td) ;
pthread_create(&sendr,nullptr ,send_message ,&td) ;

//线程等待
pthread_join(recvr,nullptr);
pthread_join(sendr,nullptr);




    //     //  客户端需要bind ，不需要用户显示的bind，一般有OS自由随机选择

    //     char buffer [SIZE];
    //     std::string  message ;
    // while(true )
    // {
    //     //客户端发送数据给server
    //      std::cout << "Please Enter@ ";
    //     getline(std::cin, message);
    //     std::cout<<message<<std::endl;
    //     sendto(sockfd, message.c_str(),message.size(),0, (  struct sockaddr *)&server ,len);
       
    //      struct sockaddr_in temp;
    //     socklen_t len = sizeof(temp);
 
    //     ssize_t s = recvfrom(sockfd, buffer, 1023, 0, (struct sockaddr*)&temp, &len);
    //   //  std::cout<<"recvfrom success"<<std::endl;
    //     if(s > 0)
    //     {
    //         buffer[s] = 0; //当成字符串处理
    //           std::cout << buffer <<   std::endl;
    //     }



    // }

    close (td.sockfd);
}